import pandas as pd
from pathlib import Path
import numpy as np
from typing import Dict, Any, Optional, Union, List, Tuple
from datetime import datetime, timedelta, time, date
import glob
import os
import json

from .utils import (_get_logger,
                             LOG_PATTERN, 
                             LogParseError,
                             DataValidationError,
                             convert_numpy_types,
                             parse_time_range)

def discover_log_files(logs_base_path: Union[str, Path], 
                      start_date: datetime,
                      end_date: datetime) -> List[Path]:
    """
    发现指定时间范围内的所有日志文件
    
    Args:
        logs_base_path: 日志基础路径 (如 'logs/')
        start_date: 开始日期 (包含)
        end_date: 结束日期 (包含)
        
    Returns:
        List[Path]: 找到的日志文件路径列表
        
    Raises:
        FileNotFoundError: 当基础路径不存在时

    Notes:
        - 查找该范围内的日志文件。
        - 日志文件格式为 'logs_base_path/YYYYMMDD/detection.log'。
    """
    logger = _get_logger()
    logs_base_path = Path(logs_base_path)
    
    if not logs_base_path.exists():
        if logger:
            logger.error(f"日志基础路径不存在: {logs_base_path}")
        raise FileNotFoundError(f"日志基础路径不存在: {logs_base_path}")
    
    log_files = []
    
    if start_date is None and end_date is None:
        if logger:
            logger.error("未指定时间范围，无法查找日志文件")
        raise ValueError("必须指定开始日期或结束日期")
    else:
        # 根据时间范围查找
        current_date = start_date or datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        end_date = end_date or datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        
        if logger:
            logger.info(f"搜索时间范围内的日志文件", 
                       start_date=start_date.strftime("%Y-%m-%d") if start_date else "未指定",
                       end_date=end_date.strftime("%Y-%m-%d") if end_date else "未指定")
        
        while current_date <= end_date:
            date_str = current_date.strftime("%Y%m%d")
            log_path = logs_base_path / date_str / "detection.log"
            
            if log_path.exists():
                log_files.append(log_path)
                if logger:
                    logger.info(f"找到日志文件: {log_path}",
                                start_date=start_date.strftime("%Y-%m-%d") if start_date else "未指定",
                                end_date=end_date.strftime("%Y-%m-%d") if end_date else "未指定")
            else:
                if logger:
                    logger.info(f"未找到日志文件: {log_path}",
                                start_date=start_date.strftime("%Y-%m-%d") if start_date else "未指定",
                                end_date=end_date.strftime("%Y-%m-%d") if end_date else "未指定")
            
            current_date += timedelta(days=1)
    
    if logger:
        logger.info(f"日志文件发现完成", total_files=len(log_files),
                    start_date=start_date.strftime("%Y-%m-%d") if start_date else "未指定",
                    end_date=end_date.strftime("%Y-%m-%d") if end_date else "未指定")
    
    return sorted(log_files)


def parse_detection_logs(log_files: List[Path]) -> pd.DataFrame:
    """
    解析多个检测日志文件
    
    此函数读取并解析多个检测系统生成的日志文件，合并提取检测结果数据。
    
    Args:
        log_files: 日志文件路径列表
        
    Returns:
        pd.DataFrame: 包含以下列的DataFrame：
            - ts (index): 时间戳 (pandas.Timestamp)
            - status: 检测状态 ('defective' 或 'normal')
            - type: 缺陷类型
            - conf: 置信度 (float, 0-1之间)
            - 其他可选字段（如frame_id, image_path等）
            
    Raises:
        LogParseError: 当日志格式无法解析时
        
    Example:
        >>> log_files = discover_log_files('logs/', start_date, end_date)
        >>> df = parse_detection_logs(log_files)
    """
    logger = _get_logger()
    if logger:
        logger.info(f"开始解析多个检测日志文件", file_count=len(log_files))

    if not log_files:
        if logger:
            logger.error("没有找到日志文件")
        return pd.DataFrame(columns=['ts', 'status', 'type', 'conf']).set_index(pd.DatetimeIndex([], name='ts'))
    
    all_records = []
    total_line_count = 0
    total_parsed_count = 0
    
    for log_path in log_files:
        if logger:
            logger.info(f"解析日志文件: {log_path}")
        
        try:
            with open(log_path, 'r', encoding='utf-8') as f:
                for line_number, line in enumerate(f, start=1):
                    total_line_count += 1
                    line = line.strip()

                    if not line: # 跳过空行
                        continue

                    match = LOG_PATTERN.match(line)
                    if not match:
                        if logger:
                            logger.error(f"无法解析日志行: {line}", 
                                           file_path=log_path, 
                                           line_number=line_number)
                        continue

                    # 提取匹配的数据
                    groups = match.groupdict()

                    try:
                        record = {
                            'ts': pd.to_datetime(groups['ts']),
                            'status': groups['status'].lower(),
                            'type': groups['type'],
                            'conf': float(groups['conf']),
                        }

                        # 解析其他字段
                        if groups['others']:
                            _parse_additional_fields(groups.get('others'), record)

                        all_records.append(record)
                        total_parsed_count += 1

                    except Exception as e:
                        if logger:
                            logger.error(f"解析日志行失败: {line}", 
                                         line_number=line_number, 
                                         file_path=log_path, 
                                         error=str(e)) 
                        continue

        except Exception as e:
            if logger:
                logger.error(f"读取日志文件失败: {log_path}", 
                             error=str(e))
            continue
        
    # 创建DataFrame
    if not all_records:
        if logger:
            logger.info(f"日志文件中没有解析到任何记录: {log_path}")
        return pd.DataFrame(columns=['ts', 'status', 'type', 'conf']).set_index(pd.DatetimeIndex([], name='ts'))
        
    df = pd.DataFrame(all_records)
    df.set_index('ts', inplace=True)
    df.sort_index(inplace=True)  # 按时间戳排序

    if logger:
        logger.info(f"多个检测日志解析完成", 
                    total_files=len(log_files), 
                    total_lines=total_line_count, 
                    valid_records=total_parsed_count)
    
    # 数据验证
    _validate_dataframe(df)

    return df

def _parse_additional_fields(others_str: str, record: Dict[str, Any]) -> None:
    """
    解析日志中的附加字段
    
    Args:
        others_str: 附加字段字符串，格式为 "key1=value1 | key2=value2"
        record: 记录字典，解析结果会添加到此字典中
    """
    for kv_pair in others_str.split('|'):
        kv_pair = kv_pair.strip()
        if '=' in kv_pair:
            key, value = kv_pair.split('=', 1)
            record[key.strip()] = value.strip()


def _validate_dataframe(df: pd.DataFrame) -> None:
    """
    验证DataFrame数据的有效性
    
    Args:
        df: 待验证的DataFrame
        
    Raises:
        DataValidationError: 当数据不符合要求时
    """
    if df.empty:
        if _get_logger():
            _get_logger().info("DataFrame为空，跳过数据验证")
        return
        
    # 检查必需的列
    required_columns = ['status', 'type', 'conf']
    missing_columns = [col for col in required_columns if col not in df.columns]
    if missing_columns:
        if _get_logger():
            _get_logger().error("DataFrame缺少必需的列", 
                               missing_columns=missing_columns, 
                               expected_format=f"必须包含 {required_columns}")
        raise DataValidationError(message=f"缺少必需的列：{missing_columns}",
                                  expected_format=f"必须包含 {required_columns}")
    
    # 检查状态值的有效性
    valid_statuses = {'defective', 'normal'}
    invalid_statuses = set(df['status'].unique()) - valid_statuses
    if invalid_statuses:
        if _get_logger():
            _get_logger().error("发现无效的状态值", 
                               invalid_values=list(invalid_statuses), 
                               expected_format=f"必须是 {valid_statuses} 中的一个")
        raise DataValidationError(message="发现无效的状态值", field_name='status', 
                                  invalid_value=list(invalid_statuses), 
                                  expected_format=f"必须是 {valid_statuses} 中的一个")    
    # 检查置信度范围
    if not df['conf'].between(0, 1).all():
        if _get_logger():
            _get_logger().error("置信度值不在0-1范围内")
        raise DataValidationError(message="置信度值不在0-1范围内", field_name='conf',
                                  invalid_value=df.loc[~df['conf'].between(0, 1), 'conf'].tolist())

def get_basic_stats(logs_base_path: Union[str, Path],
                                 time_range_spec: Union[str, Dict[str, Any]],
                                 resample_freq: Optional[str] = None) -> Dict[str, Any]:
    """
    根据时间范围获取基础统计数据
    
    Args:
        logs_base_path: 日志基础路径
        time_range_spec: 时间范围规格
        resample_freq: 可选的重采样频率，如果提供则返回时间序列数据
        
    Returns:
        Dict[str,Any]: 包含基础统计信息的字典
        
    Example:
        >>> # 获取最近24小时的统计
        >>> stats = get_basic_stats('logs/', 'latest_hours:24')
        >>> 
        >>> # 获取指定日期范围的统计，并按小时重采样
        >>> stats = get_basic_stats(
        ...     'logs/', 
        ...     {'start': '2024-01-01', 'end': '2024-01-07'},
        ...     resample_freq='1h'
        ... )
    """
    logger = _get_logger()
    if logger:
        logger.info("开始获取基础统计数据", time_range_spec=str(time_range_spec),
                    freq=resample_freq)
    
    try:
        # 解析时间范围
        start_time, end_time = parse_time_range(time_range_spec)
        
        # 发现日志文件
        log_files = discover_log_files(logs_base_path, start_time, end_time)
        
        # 解析日志数据
        df = parse_detection_logs(log_files)
        
        # 根据时间范围过滤数据
        if start_time and end_time:
            df = df[(df.index >= start_time) & (df.index <= end_time)]
        elif start_time:
            df = df[df.index >= start_time]
        elif end_time:
            df = df[df.index <= end_time]
        
        # 计算基础统计
        basic_stats = compute_basic_stats(df, (start_time, end_time))
        
        result = {
            'basic_stats': convert_numpy_types(basic_stats),
            'metadata': {
                'query_time_range_spec': str(time_range_spec),
                'log_files_found': len(log_files),
                'total_records_found': len(df),
                'generated_at': str(datetime.now()),
            }
        }
        
        # 如果指定了重采样频率，添加时间序列数据
        if resample_freq and not df.empty:
            time_series = resample_time_stats(df, resample_freq)
            time_series_with_idx = time_series.reset_index()
            time_series_with_idx.rename(columns={'index': 'timestamp'}, inplace=True)
            result['time_series'] = convert_numpy_types(time_series_with_idx.to_dict('records'))
            result['metadata']['resample_frequency'] = resample_freq
        
        if logger:
            logger.info("基础统计数据获取完成", 
                       total_records=result['metadata']['total_records_found'],
                       log_files=result['metadata']['log_files_found'])
        
        return result
        
    except Exception as e:
        if logger:
            logger.error("获取基础统计数据失败", 
                         time_range_spec=str(time_range_spec), 
                         error=str(e))
        raise

def compute_basic_stats(df: pd.DataFrame, 
                       time_range: Optional[Tuple[datetime, datetime]] = None) -> Dict[str, Union[int, float, str]]:
    """
    计算基础生产统计指标
    
    根据DataFrame中的检测数据计算基本的生产统计信息。
    
    Args:
        df: 包含检测数据的DataFrame，必须包含'status'列
        time_range: 时间范围元组 (start_time, end_time)，用于统计说明
        
    Returns:
        Dict[str, Union[int, float, str]]: 包含以下统计指标的字典：
            - total: 检测总数 (int)
            - defective: 缺陷产品数 (int)
            - passed: 合格产品数 (int)
            - defect_rate: 缺陷率 (float, 0-1之间)
            - pass_rate: 合格率 (float, 0-1之间)
            - time_range_start: 统计时间范围开始 (str)
            - time_range_end: 统计时间范围结束 (str)
            - actual_data_start: 实际数据开始时间 (str)
            - actual_data_end: 实际数据结束时间 (str)
            
    Raises:
        DataValidationError: 当DataFrame为空或缺少必需列时
        
    Example:
        >>> stats = compute_basic_stats(df, (start_time, end_time))
        >>> print(f"时间范围 {stats['time_range_start']} 到 {stats['time_range_end']}")
        >>> print(f"总检测数: {stats['total']}, 缺陷率: {stats['defect_rate']:.2%}")
    """
    logger = _get_logger()
    
    if df.empty:
        if logger:
            logger.info("DataFrame为空，返回零值统计")
        return {
            'total': 0,
            'defective': 0,
            'passed': 0,
            'defect_rate': 0.0,
            'pass_rate': 0.0,
            'time_range_start': str(time_range[0]) if time_range and time_range[0] else None,
            'time_range_end': str(time_range[1]) if time_range and time_range[1] else None,
            'actual_data_start': None,
            'actual_data_end': None,
        }
    
    if 'status' not in df.columns:
        if logger:
            logger.error("DataFrame缺少必需的'status'列")
        raise DataValidationError("DataFrame缺少必需的'status'列")
    
    # 计算基础统计
    total = len(df)
    defective = (df['status'] == 'defective').sum()
    passed = total - defective
    
    # 避免除零错误
    defect_rate = defective / total if total > 0 else 0.0
    pass_rate = passed / total if total > 0 else 0.0
    
    # 获取实际数据时间范围
    actual_start = str(df.index.min()) if not df.empty else None
    actual_end = str(df.index.max()) if not df.empty else None
    
    stats = {
        'total': int(total),
        'defective': int(defective),
        'passed': int(passed),
        'defect_rate': float(defect_rate),
        'pass_rate': float(pass_rate),
        'time_range_start': str(time_range[0]) if time_range and time_range[0] else None,
        'time_range_end': str(time_range[1]) if time_range and time_range[1] else None,
        'actual_data_start': actual_start,
        'actual_data_end': actual_end,
    }
    
    if logger:
        logger.info("基础统计计算完成", 
                   total=stats['total'],
                   defective=stats['defective'],
                   defect_rate=f"{stats['defect_rate']:.2%}",
                   passed=stats['passed'],
                   pass_rate=f"{stats['pass_rate']:.2%}",
                   time_range_start=stats['time_range_start'],
                   time_range_end=stats['time_range_end'])
    
    return stats


def resample_time_stats(df: pd.DataFrame, freq: str = '1h') -> pd.DataFrame:
    """
    按时间频率重采样统计数据
    
    将检测数据按指定的时间频率进行聚合统计，用于时间趋势分析。
    
    Args:
        df: 包含检测数据的DataFrame，索引必须为时间戳
        freq: 重采样频率，支持pandas频率字符串：
            - '1h': 每小时
            - '30T' 或 '30min': 每30分钟  
            - '1D': 每天
            - '1W': 每周
            - '1M': 每月
            - '1A': 每年
            
    Returns:
        pd.DataFrame: 包含以下列的时间序列DataFrame：
            - total: 该时间段内的检测总数 (int)
            - defective: 该时间段内的缺陷数量 (int)
            - defect_rate: 该时间段内的缺陷率 (float, 0-1之间)
            索引为时间戳
            
    Raises:
        DataValidationError: 当DataFrame索引不是时间类型时
        ValueError: 当频率字符串无效时
        
    Example:
        >>> hourly_stats = resample_time_stats(df, '1H')
        >>> print(hourly_stats.tail())
                           total  defective  defect_rate
        2024-01-01 08:00:00    120          6     0.050
        2024-01-01 09:00:00    115          8     0.070
    """
    logger = _get_logger()

    if df.empty:
        if logger:
            logger.info("DataFrame为空，返回空的时间统计")
        return pd.DataFrame(columns=['total', 'defective', 'defect_rate'])
    
    # 验证索引是否为时间类型
    if not isinstance(df.index, pd.DatetimeIndex):
        if logger:
            logger.error("DataFrame索引不是DatetimeIndex类型", 
                         index_type=type(df.index).__name__)
        raise DataValidationError("DataFrame索引必须为DatetimeIndex类型")
    
    if 'status' not in df.columns:
        if logger:
            logger.error("DataFrame缺少'status'列")
        raise DataValidationError("DataFrame缺少'status'列")
    
    try:
        # 按频率重采样
        resampled = df.resample(freq)
            
        # 计算统计指标
        total_counts = resampled['status'].count()
        defective_counts = resampled['status'].apply(lambda x: (x == 'defective').sum())
            
        # 构建结果DataFrame
        time_stats = pd.DataFrame({
            'total': total_counts,
            'defective': defective_counts,
        })
            
        # 计算缺陷率，避免除零
        time_stats['defect_rate'] = np.where(
            time_stats['total'] > 0,
            time_stats['defective'] / time_stats['total'],
            0.0
        )
        
        # 填充缺失值
        time_stats = time_stats.fillna(0)
        
        # 转换数据类型
        time_stats['total'] = time_stats['total'].astype(int)
        time_stats['defective'] = time_stats['defective'].astype(int)
        
        if logger:
            logger.info("时间重采样完成", 
                    frequency=freq, 
                    time_periods=len(time_stats))
        
        return time_stats
        
    except ValueError as e:
        if logger:
            logger.error("重采样频率字符串无效", 
                         frequency=freq, 
                         error=str(e))
        raise ValueError(f"无效的频率字符串 '{freq}': {e}")


def get_defect_type_stats(logs_base_path: Union[str, Path],
                                       time_range_spec: Union[str, Dict[str, Any]],
                                       resample_freq: Optional[str] = None) -> Dict[str, Any]:
    """
    根据时间范围获取缺陷类型统计数据
    
    Args:
        logs_base_path: 日志基础路径
        time_range_spec: 时间范围规格
        resample_freq: 可选的重采样频率，如果提供则返回按时间分组的缺陷类型统计
        
    Returns:
        Dict[str, Any]: 包含缺陷类型统计信息的字典
        
    Example:
        >>> # 获取最近7天的缺陷类型统计
        >>> stats = get_defect_type_stats('logs/', 'latest_days:7')
        >>> 
        >>> # 获取指定日期范围的缺陷类型统计，并按天分组
        >>> stats = get_defect_type_stats(
        ...     'logs/', 
        ...     {'start': '2024-01-01', 'end': '2024-01-07'},
        ...     resample_freq='1D'
        ... )
    """
    logger = _get_logger()
    if logger:
        logger.info("开始获取缺陷类型统计数据", time_range_spec=str(time_range_spec))
    
    try:
        # 解析时间范围
        start_time, end_time = parse_time_range(time_range_spec)
        
        # 发现日志文件
        log_files = discover_log_files(logs_base_path, start_time, end_time)
        
        # 解析日志数据
        df = parse_detection_logs(log_files)
        
        # 根据时间范围过滤数据
        if start_time and end_time:
            df = df[(df.index >= start_time) & (df.index <= end_time)]
        elif start_time:
            df = df[df.index >= start_time]
        elif end_time:
            df = df[df.index <= end_time]
        
        # 计算缺陷类型统计
        defect_type_stats = compute_defect_type_stats(df, (start_time, end_time))
        
        result = {
            'defect_type_stats': convert_numpy_types(defect_type_stats),
            'metadata': {
                'query_time_range_spec': str(time_range_spec),
                'log_files_found': len(log_files),
                'total_records_found': len(df),
                'generated_at': str(datetime.now()),
            }
        }
        
        # 如果指定了重采样频率，添加按时间分组的缺陷类型统计
        if resample_freq and not df.empty:
            defective_df = df[df['status'] == 'defective']
            if not defective_df.empty:
                # 按时间重采样，然后统计每个时间段的缺陷类型
                resampled_groups = defective_df.resample(resample_freq)
                time_series_defect_types = []
                
                for timestamp, group in resampled_groups:
                    if not group.empty:
                        type_counts = group['type'].value_counts()
                        total_defects_in_period = len(group)
                        
                        period_stats = {
                            'timestamp': str(timestamp),
                            'total_defects': total_defects_in_period,
                            'defect_types': []
                        }
                        
                        for defect_type, count in type_counts.items():
                            ratio = count / total_defects_in_period
                            period_stats['defect_types'].append({
                                'type': defect_type,
                                'count': int(count),
                                'ratio': float(ratio)
                            })
                        
                        time_series_defect_types.append(period_stats)
                
                result['time_series_defect_types'] = time_series_defect_types
                result['metadata']['resample_frequency'] = resample_freq
        
        if logger:
            logger.info("缺陷类型统计数据获取完成", 
                       total_records=result['metadata']['total_records_found'],
                       log_files=result['metadata']['log_files_found'],
                       total_defects=result['defect_type_stats']['total_defects'])
        
        return result
        
    except Exception as e:
        if logger:
            logger.error("获取缺陷类型统计数据失败", 
                         time_range_spec=str(time_range_spec), 
                         error=str(e))
        raise
    
def compute_defect_type_stats(df: pd.DataFrame, 
                             time_range: Optional[Tuple[datetime, datetime]] = None) -> Dict[str, Any]:
    """
    计算缺陷类型统计
    
    分析不同缺陷类型的数量分布和占比情况。
    
    Args:
        df: 包含检测数据的DataFrame，必须包含'status'和'type'列
        time_range: 时间范围元组 (start_time, end_time)，用于统计说明
        
    Returns:
        Dict[str, Any]: 包含以下信息的字典：
            - defect_types: 各缺陷类型统计列表，每项包含：
                - type: 缺陷类型名称
                - count: 数量
                - ratio: 在所有缺陷中的占比
            - total_defects: 缺陷总数
            - time_range_start: 统计时间范围开始
            - time_range_end: 统计时间范围结束
            - actual_data_start: 实际数据开始时间
            - actual_data_end: 实际数据结束时间
            
    Example:
        >>> type_stats = compute_defect_type_stats(df, (start_time, end_time))
        >>> print(f"缺陷总数: {type_stats['total_defects']}")
        >>> for defect in type_stats['defect_types']:
        ...     print(f"{defect['type']}: {defect['count']} ({defect['ratio']:.1%})")
    """
    logger = _get_logger()
    
    # 获取实际数据时间范围
    actual_start = str(df.index.min()) if not df.empty else None
    actual_end = str(df.index.max()) if not df.empty else None
    
    if df.empty:
        if logger:
            logger.info("DataFrame为空，返回空的缺陷类型统计")
        return {
            'defect_types': [],
            'total_defects': 0,
            'time_range_start': str(time_range[0]) if time_range and time_range[0] else None,
            'time_range_end': str(time_range[1]) if time_range and time_range[1] else None,
            'actual_data_start': actual_start,
            'actual_data_end': actual_end,
        }
    
    # 验证必需的列
    required_columns = ['status', 'type']
    missing_columns = [col for col in required_columns if col not in df.columns]
    if missing_columns:
        if logger:
            logger.error("DataFrame缺少必需的列", 
                         missing_columns=missing_columns, 
                         expected_format=f"必须包含 {required_columns}")
        raise DataValidationError(message=f"缺少必需的列：{missing_columns}",
                                  expected_format=f"必须包含 {required_columns}")
    
    # 筛选缺陷记录
    defective_df = df[df['status'] == 'defective']
    
    if defective_df.empty:
        if logger:
            logger.info("未发现缺陷记录")
        return {
            'defect_types': [],
            'total_defects': 0,
            'time_range_start': str(time_range[0]) if time_range and time_range[0] else None,
            'time_range_end': str(time_range[1]) if time_range and time_range[1] else None,
            'actual_data_start': actual_start,
            'actual_data_end': actual_end,
        }
    
    # 统计各类型数量
    type_counts = defective_df['type'].value_counts()
    total_defective = len(defective_df)
    
    # 构建结果
    defect_types_list = []
    for defect_type, count in type_counts.items():
        ratio = count / total_defective
        defect_types_list.append({
            'type': defect_type,
            'count': int(count),
            'ratio': float(ratio)
        })
    
    result = {
        'defect_types': defect_types_list,
        'total_defects': int(total_defective),
        'time_range_start': str(time_range[0]) if time_range and time_range[0] else None,
        'time_range_end': str(time_range[1]) if time_range and time_range[1] else None,
        'actual_data_start': actual_start,
        'actual_data_end': actual_end,
    }
    
    if logger:
        logger.info("缺陷类型统计完成", 
                   defect_types_count=len(defect_types_list),
                   total_defective=total_defective,
                   time_range_start=result['time_range_start'],
                   time_range_end=result['time_range_end'])
    
    return result


def daily_summary(log_base_path: Union[str, Path], output_base_dir: Union[str, Path], target_date: Optional[date] = None) -> None:
    """
    每日统计函数，在每天凌晨0点被调用，统计前一天一整天的数据，
    生成 JSON 文件并存放在 output_base_dir 里对应的日期目录中。

    Args:
        logs_base_path: 数据统计模块的日志文件基础路径。
        output_base_dir: 存储生成的统计 JSON 文件的根目录。
        date: 可选的日期参数，如果提供则统计该日期的数据，否则统计昨天的数据。
    """
    logger = _get_logger()

    # 如果未提供 target_date，则默认为昨天
    if target_date is None:
        target_date = date.today() - timedelta(days=1)

    # 计算开始和结束时间
    start_time = datetime.combine(target_date, time.min)  # 当天0点
    end_time = datetime.combine(target_date, time.max)    # 当天23:59:59.999999

    time_range_spec = {
        "start": start_time.strftime("%Y-%m-%d %H:%M:%S.%f"),  # 统一到毫秒
        "end": end_time.strftime("%Y-%m-%d %H:%M:%S.%f")       # 统一到毫秒
    }

    resample_freq = None  # 统计一整天数据，不需要重采样

    daily_stats_output = {}  # 存储最终要写入 JSON 的数据

    if logger:
        logger.info("开始每日统计", 
                    target_date=target_date.strftime("%Y-%m-%d"), 
                    start=time_range_spec['start'], 
                    end=time_range_spec['end'])
    

    # 调用基础统计数据接口
    try:
        basic_stats = get_basic_stats(log_base_path, time_range_spec, resample_freq)
        daily_stats_output["basic_stats"] = basic_stats
        
        # 检查基础统计数据是否找到日志文件或记录
        if basic_stats["metadata"]["log_files_found"] == 0:
            daily_stats_output["basic_stats_status"] = "未找到日志文件。"
        elif basic_stats["metadata"]["total_records_found"] == 0:
            daily_stats_output["basic_stats_status"] = "已找到日志文件，但未找到匹配的记录。"
        else:
            daily_stats_output["basic_stats_status"] = "数据统计成功。"
            if basic_stats["basic_stats"]["total"] == 0:
                daily_stats_output["basic_stats_display_message"] = "暂无数据"
            else:
                daily_stats_output["basic_stats_display_message"] = "数据已生成"

    except Exception as e:
        if logger:
            logger.error("调用基础统计接口失败", error=str(e), time_range_spec=time_range_spec)
        daily_stats_output["basic_stats_status"] = f"调用基础统计接口发生错误: {str(e)}"
        daily_stats_output["basic_stats"] = {} # 确保即使出错也有此字段

    # 调用缺陷类型统计接口
    try:
        defect_type_stats = get_defect_type_stats(log_base_path, time_range_spec, resample_freq)
        daily_stats_output["defect_type_stats"] = defect_type_stats
        
        # 检查缺陷类型统计数据是否找到日志文件或记录
        if defect_type_stats["metadata"]["log_files_found"] == 0:
            daily_stats_output["defect_type_stats_status"] = "未找到日志文件。"
        elif defect_type_stats["metadata"]["total_records_found"] == 0:
            daily_stats_output["defect_type_stats_status"] = "已找到日志文件，但未找到匹配的记录。"
        else:
            daily_stats_output["defect_type_stats_status"] = "数据统计成功。"
            if defect_type_stats["defect_type_stats"]["total_defects"] == 0:
                daily_stats_output["defect_type_stats_display_message"] = "暂无数据"
            else:
                daily_stats_output["defect_type_stats_display_message"] = "数据已生成"

    except Exception as e:
        if logger:
            logger.error("调用缺陷类型统计接口失败", error=str(e), time_range_spec=time_range_spec)
        daily_stats_output["defect_type_stats_status"] = f"调用缺陷类型统计接口发生错误: {str(e)}"
        daily_stats_output["defect_type_stats"] = {} # 确保即使出错也有此字段


    # 准备输出目录和文件名
    # 格式化日期作为目录名
    output_date_dir = target_date.strftime("%Y%m%d")
    full_output_dir = os.path.join(output_base_dir, output_date_dir)
    output_filename = os.path.join(full_output_dir, "daily_summary.json")

    # 创建目录（如果不存在）
    os.makedirs(full_output_dir, exist_ok=True)

    # 将合并后的统计数据保存为 JSON 文件
    try:
        with open(output_filename, 'w', encoding='utf-8') as f:
            json.dump(daily_stats_output, f, ensure_ascii=False, indent=4)
        if logger:
            logger.info("每日统计数据保存成功", output_filename=output_filename)

    except IOError as e:
        if logger:
            logger.error("保存每日统计数据失败", output_filename=output_filename, error=str(e))
        
    except Exception as e:
        if logger:
            logger.error("保存每日统计数据时发生未知错误", output_filename=output_filename, error=str(e))